/**
 * 防抖函数
 * @param fn 事件触发的操作
 * @param duration 多少毫秒内连续触发事件，不会执行
 * @returns {Function}
 */
export function debounce(fn, duration = 200) {
  let timer = null
  return function() {
    const self = this
    const args = arguments
    timer && clearTimeout(timer)
    timer = setTimeout(function() {
      fn.apply(self, args)
    }, duration)
  }
}

/**
 * @description 绑定事件 on(element, event, handler)
 */
export const on = (function() {
  if (document.addEventListener) {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.addEventListener(event, handler, false)
      }
    }
  } else {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.attachEvent('on' + event, handler)
      }
    }
  }
})(document)

/**
 * @description 解绑事件 off(element, event, handler)
 */
export const off = (function() {
  if (document.removeEventListener) {
    return function(element, event, handler) {
      if (element && event) {
        element.removeEventListener(event, handler, false)
      }
    }
  } else {
    return function(element, event, handler) {
      if (element && event) {
        element.detachEvent('on' + event, handler)
      }
    }
  }
})(document)

/**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass(ele, cls) {
  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}

/**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function addClass(ele, cls) {
  if (!hasClass(ele, cls)) ele.className += ' ' + cls
}

/**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
    ele.className = ele.className.replace(reg, ' ')
  }
}

/**
 * * 获取所有子元素 getOneChildElement
 * @param {element} startElement
 * @param {function} rule
 * @param {string} type
 */
export const getAllChildElement = function(startElement, rule, type = 'childNodes') {
  const all = []
  if (rule(startElement)) return [startElement]
  const getChidElement = function(element, rule, all) {
    const elements = element[type]
    for (let i = 0; i < elements.length; i++) {
      const child = elements[i]
      if (child.$options.name === 'VForm' || child.$options.name === 'ElPagination') continue
      if (rule(child)) {
        all.push(child)
        break
      } else {
        getChidElement(child, rule, all)
      }
    }
  }
  getChidElement(startElement, rule, all)
  return all
}

/**
 * * 获取所有子组件 getAllChildComponent
 * @param {element} component
 * @param {function} rule
 */
export const getAllChildComponent = (component, rule = child => child.focus) => getAllChildElement(component, rule, '$children')

/**
 * * 获取属性值
 * @param {node} node
 */
export const getStyle = function(elem, prop) {
  return window.getComputedStyle(elem, null).getPropertyValue(prop)
}
/**
 * * 获取节点文本宽度
 * @param {node} node
 */
export const getTextWidth = function(node) {
  const range = document.createRange()
  range.setStart(node, 0)
  range.setEnd(node, node.childNodes.length)
  const rangeWidth = range.getBoundingClientRect().width
  const padding = parseInt(getStyle(node, 'padding-left')) + parseInt(getStyle(node, 'padding-right'))
  return padding + rangeWidth
}

/**
 * * 判断文本是否溢出
 * @param {node} node
 */
export const textOverflow = function(node) {
  return getTextWidth(node) - 0.3 > node.getBoundingClientRect().width
}

/**
 * 获取内容的长度
 * @param value
 * @return 内容的长度
 */
export const getStrSize = (value) => {
  if (!value) {
    return 0
  }
  const charCount = value.split('').reduce((prev, curr) => {
    // 英文字母和数字等算一个字符；这个暂时还不完善；
    if (/[a-z]|[0-9]|[,;.!@#-+/\\$%^*()<>?:"'{}~]/i.test(curr)) {
      return prev + 1
    }
    // 其他的算是2个字符
    return prev + 2
  }, 0)

  // 向上取整，防止出现半个字的情况
  return Math.ceil(charCount / 2)
}

/**
 * * 格式化文件大小
 * @param {number} size
 * @param {number} num
 */
export const formatSize = function(size, num = 4) {
  if (!size) return 0
  return (size / 1024 / 1024).toFixed(num + 1).substring(0, num + 2) + 'MB'
}

